package com.controller;

import com.alibaba.fastjson.JSON;
import com.annotation.IgnoreAuth;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.MatchRequest;
import com.baidu.aip.util.Base64Util;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.service.CommonService;
import com.service.ConfigService;
import com.utils.BaiduUtil;
import com.utils.FileUtil;
import com.utils.R;
import com.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 通用接口
 */
@RestController
public class CommonController {
    private static final Logger logger = LoggerFactory.getLogger(CommonController.class);
    private static AipFace client = null;
    private static String BAIDU_DITU_AK = null;
    @Autowired
    private CommonService commonService;
    @Autowired
    private ConfigService configService;

    /**
     * 根据经纬度获取位置信息
     * @param lng 经度
     * @param lat 纬度
     * @return 返回位置信息的数据响应对象
     */
    @RequestMapping("/location")
    public R location(String lng, String lat) {
        // 检查是否已经获取到百度地图API密钥（AK），如果未获取到，则尝试从配置中获取
        if (BAIDU_DITU_AK == null) {
            // 从配置服务中根据名称查询百度地图AK配置
            BAIDU_DITU_AK = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "baidu_ditu_ak")).getValue();
            // 如果获取到的AK仍为null，则返回错误提示，要求在配置管理中正确配置baidu_ditu_ak
            if (BAIDU_DITU_AK == null) {
                return R.error("请在配置管理中正确配置baidu_ditu_ak");
            }
        }
        // 调用百度地图工具类，根据经纬度获取城市信息
        Map<String, String> map = BaiduUtil.getCityByLonLat(BAIDU_DITU_AK, lng, lat);
        // 返回成功数据响应，包含通过百度地图API获取的城市信息
        return R.ok().put("data", map);
    }

    /**
     * 人脸比对
     * @param face1   人脸1
     * @param face2   人脸2
     * @param request HTTP请求对象，用于获取上传文件的路径
     * @return 比对结果
     */
    @RequestMapping("/matchFace")
    public R matchFace(String face1, String face2, HttpServletRequest request) {
        // 当client为空时，表示尚未初始化，需要进行初始化操作
        if (client == null) {
            // 从配置服务中获取APIKey和SecretKey，用于百度AI服务的认证
            String APIKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "APIKey")).getValue();
            String SecretKey = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "SecretKey")).getValue();
            // 获取百度AI服务的认证令牌
            String token = BaiduUtil.getAuth(APIKey, SecretKey);
            // 如果令牌获取失败，返回错误信息
            if (token == null) {
                return R.error("请在配置管理中正确配置APIKey和SecretKey");
            }
            // 初始化百度人脸服务client，并设置超时时间
            client = new AipFace(null, APIKey, SecretKey);
            client.setConnectionTimeoutInMillis(2000);
            client.setSocketTimeoutInMillis(60000);
        }
        // 执行人脸比对操作
        JSONObject res = null;
        try {
            // 根据传入的文件名获取文件完整路径
            File file1 = new File(request.getSession().getServletContext().getRealPath("/upload") + "/" + face1);
            File file2 = new File(request.getSession().getServletContext().getRealPath("/upload") + "/" + face2);
            // 将文件转换为Base64编码字符串
            String img1 = Base64Util.encode(FileUtil.FileToByte(file1));
            String img2 = Base64Util.encode(FileUtil.FileToByte(file2));
            // 创建匹配请求对象
            MatchRequest req1 = new MatchRequest(img1, "BASE64");
            MatchRequest req2 = new MatchRequest(img2, "BASE64");
            ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
            requests.add(req1);
            requests.add(req2);
            // 发送匹配请求并获取结果
            res = client.match(requests);
            // 打印比对结果
            System.out.println(res.get("result"));
        } catch (FileNotFoundException e) {
            // 文件不存在异常处理
            e.printStackTrace();
            return R.error("文件不存在");
        } catch (IOException e) {
            // IO异常处理
            e.printStackTrace();
        }
        // 返回比对结果
        return R.ok().put("data", com.alibaba.fastjson.JSONObject.parse(res.get("result").toString()));
    }

    /**
     * 获取table表中的column列表(联动接口)
     * 该方法通过接收表名和列名，可选的级别和父级参数，来查询并返回指定条件下的数据列表
     * @param tableName  表名，用于指定查询的数据表
     * @param columnName 列名，用于指定查询的数据列
     * @param level      可选的级别参数，用于某些需要级别的查询
     * @param parent     可选的父级参数，用于某些需要父级信息的查询
     * @return 返回一个响应对象，包含查询到的数据列表
     */
    @RequestMapping("/option/{tableName}/{columnName}")
    @IgnoreAuth
    public R getOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, String level, String parent) {
        // 创建参数映射，用于存放查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        // 将表名放入参数映射
        params.put("table", tableName);
        // 将列名放入参数映射
        params.put("column", columnName);
        // 如果级别参数不为空，则加入参数映射
        if (StringUtils.isNotBlank(level)) {
            params.put("level", level);
        }
        // 如果父级参数不为空，则加入参数映射
        if (StringUtils.isNotBlank(parent)) {
            params.put("parent", parent);
        }
        // 调用服务方法，根据参数映射获取数据列表
        List<String> data = commonService.getOption(params);
        // 返回一个成功的响应对象，并将数据列表放入响应对象中
        return R.ok().put("data", data);
    }

    /**
     * 根据table中的column获取单条记录
     * 该方法通过接收数据库表名、列名和列值参数，查询并返回匹配的单条记录。
     * 使用了@RequestMapping注解来处理HTTP GET请求，@IgnoreAuth注解来忽略认证。
     * 参数通过路径变量和请求参数方式获取。
     * @param tableName   数据库中的表名
     * @param columnName  需要查询的列名
     * @param columnValue 查询列对应的值
     * @return 包含查询结果的R对象
     */
    @RequestMapping("/follow/{tableName}/{columnName}")
    @IgnoreAuth
    public R getFollowByOption(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, @RequestParam String columnValue) {
        // 创建参数映射对象
        Map<String, Object> params = new HashMap<String, Object>();
        // 将表名、列名和列值放入参数映射对象
        params.put("table", tableName);
        params.put("column", columnName);
        params.put("columnValue", columnValue);
        // 调用通用服务的查询方法，传入参数映射对象，获取查询结果
        Map<String, Object> result = commonService.getFollowByOption(params);
        // 将查询结果放入R对象中，并返回
        return R.ok().put("data", result);
    }


    /**
     * 修改table表的sfsh状态
     * 通过HTTP POST请求处理指定表名的审核操作
     * 此方法将表名添加到请求体中，并调用通用服务的sh方法进行状态修改
     * @param tableName 表名，用于指定哪个表的状态需要修改
     * @param map       请求体，包含要修改的状态信息
     * @return 返回一个R对象，表示操作结果
     */
    @RequestMapping("/sh/{tableName}")
    public R sh(@PathVariable("tableName") String tableName, @RequestBody Map<String, Object> map) {
        // 将表名加入请求体，以便后续处理
        map.put("table", tableName);
        // 调用通用服务的方法，执行状态修改操作
        commonService.sh(map);
        // 返回操作成功的响应
        return R.ok();
    }

    /**
     * 获取需要提醒的记录数
     * 通过HTTP GET请求提供服务，用于根据表名、列名、类型及参数条件获取提醒的记录数量
     * 主要应用于数字和日期类型的字段提醒，通过计算和条件组装，调用commonService的服务获取提醒数据的数量
     * @param tableName  表名，用于指定查询的表
     * @param columnName 列名，用于指定查询的列
     * @param type       类型，1代表数字类型，2代表日期类型，用于确定提醒逻辑的执行方式
     * @param map        参数映射，用于装载查询条件
     * @return 返回一个响应对象，包含状态和提醒记录的数量
     */
    @RequestMapping("/remind/{tableName}/{columnName}/{type}")
    @IgnoreAuth
    public R remindCount(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName, @PathVariable("type") String type, @RequestParam Map<String, Object> map) {
        // 将表名、列名和类型添加到参数映射中，以便后续使用
        map.put("table", tableName);
        map.put("column", columnName);
        map.put("type", type);
        // 如果类型为日期类型，处理日期提醒逻辑
        if (type.equals("2")) {
            // 使用指定格式解析日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            // 获取当前时间
            Calendar c = Calendar.getInstance();
            // 初始化提醒开始和结束日期
            Date remindStartDate = null;
            Date remindEndDate = null;
            // 如果提供了提醒开始条件，则计算提醒开始日期
            if (map.get("remindstart") != null) {
                Integer remindStart = Integer.parseInt(map.get("remindstart").toString());
                // 设置时间为当前时间，并添加提醒开始天数
                c.setTime(new Date());
                c.add(Calendar.DAY_OF_MONTH, remindStart);
                remindStartDate = c.getTime();
                // 将计算后的日期字符串放回参数映射
                map.put("remindstart", sdf.format(remindStartDate));
            }
            // 如果提供了提醒结束条件，则计算提醒结束日期
            if (map.get("remindend") != null) {
                Integer remindEnd = Integer.parseInt(map.get("remindend").toString());
                // 设置时间为当前时间，并添加提醒结束天数
                c.setTime(new Date());
                c.add(Calendar.DAY_OF_MONTH, remindEnd);
                remindEndDate = c.getTime();
                // 将计算后的日期字符串放回参数映射
                map.put("remindend", sdf.format(remindEndDate));
            }
        }
        // 调用commonService的remindCount方法，传入组装好的参数映射，获取提醒记录数
        int count = commonService.remindCount(map);
        // 构造并返回一个成功的响应对象，包含提醒记录的数量
        return R.ok().put("count", count);
    }

    /**
     * 图表统计
     * 该方法用于根据不同的tableName从数据库获取统计信息，并返回这些信息
     * 使用了路径变量tableName来指定查询的表名，确保了查询的灵活性和针对性
     * 此外，通过@RequestParam接收一个参数映射，允许在查询中传递额外的过滤或排序参数
     * @param tableName 数据库表名，用于指定查询的数据来源
     * @param params    查询参数映射，可能包含额外的查询条件
     * @return 包含统计结果的数据对象，使用R类封装以支持统一的API响应格式
     */
    @IgnoreAuth
    @RequestMapping("/group/{tableName}")
    public R group1(@PathVariable("tableName") String tableName, @RequestParam Map<String, Object> params) {
        // 将表名存入参数映射，用于后续的查询操作
        params.put("table1", tableName);
        // 调用服务层方法，执行图表统计查询
        List<Map<String, Object>> result = commonService.chartBoth(params);
        // 构造成功响应，携带查询结果作为数据体
        return R.ok().put("data", result);
    }


    /**
     * 单列求和
     * 该方法用于对指定表中的某一列进行求和操作，并返回求和结果
     * 通过路径变量传入表名和列名，然后将这些参数用于数据库查询
     * @param tableName  数据表名称，用于指定需要操作的数据表
     * @param columnName 数据列名称，用于指定需要求和的列
     * @return 返回一个R对象，包含求和结果的数据
     */
    @RequestMapping("/cal/{tableName}/{columnName}")
    @IgnoreAuth
    public R cal(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) {
        // 创建一个参数映射，用于存放表名和列名，之后作为查询参数使用
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("table", tableName);
        params.put("column", columnName);
        // 调用通用服务的求和方法，执行数据库查询并得到结果
        Map<String, Object> result = commonService.selectCal(params);
        // 将求和结果放入R对象中，并返回给客户端
        return R.ok().put("data", result);
    }

    /**
     * 分组统计
     * 该方法用于根据指定的表名和列名进行数据的分组统计
     * 通过调用commonService中的selectGroup方法，传入包含表名和列名的参数，
     * 获取分组统计结果，并将结果返回给客户端
     */
    @RequestMapping("/group/{tableName}/{columnName}")
    @IgnoreAuth
    public R group(@PathVariable("tableName") String tableName, @PathVariable("columnName") String columnName) {
        // 创建参数映射，用于存储SQL查询所需的表名和列名参数
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("table", tableName);
        params.put("column", columnName);
        // 调用commonService的selectGroup方法，执行分组统计查询
        List<Map<String, Object>> result = commonService.selectGroup(params);
        // 返回分组统计结果
        return R.ok().put("data", result);
    }

    /**
     * 按值统计接口
     * 该接口通过HTTP请求处理，用于统计特定数据表中两个列之间的关系
     * 主要用于展示在数据分析场景中，两个变量之间的分布情况
     * @param tableName   表名，用于指定数据来源
     * @param xColumnName X轴列名，用于指定统计结果中X轴的数据来源
     * @param yColumnName Y轴列名，用于指定统计结果中Y轴的数据来源
     * @return 返回一个R对象，包含统计结果
     */
    @RequestMapping("/value/{tableName}/{xColumnName}/{yColumnName}")
    @IgnoreAuth
    public R value(@PathVariable("tableName") String tableName, @PathVariable("yColumnName") String yColumnName, @PathVariable("xColumnName") String xColumnName) {
        // 创建参数映射，用于存储SQL查询所需的参数
        Map<String, Object> params = new HashMap<String, Object>();
        // 将表名放入参数映射
        params.put("table", tableName);
        // 将X轴列名放入参数映射
        params.put("xColumn", xColumnName);
        // 将Y轴列名放入参数映射
        params.put("yColumn", yColumnName);
        // 调用commonService的selectValue方法，执行SQL查询并获取结果
        List<Map<String, Object>> result = commonService.selectValue(params);
        // 返回一个成功的响应，携带统计结果数据
        return R.ok().put("data", result);
    }


    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

    /**
     * 查询字典表的分组求和
     * 该方法通过参数查询字典表，并返回分组求和的结果
     * 主要用于需要对字典数据进行统计和汇总的场景
     * @param params 查询参数，为一个包含键值对的Map，键为字符串类型，值为对象类型
     * @return 返回一个封装了分组求和结果的R对象，其中包含的数据为List<Map<String, Object>>类型
     */
    @RequestMapping("/newSelectGroupSum")
    public R newSelectGroupSum(@RequestParam Map<String, Object> params) {
        logger.debug("newSelectGroupSum:,,Controller:{},,params:{}", this.getClass().getName(), params);
        List<Map<String, Object>> result = commonService.newSelectGroupSum(params);
        return R.ok().put("data", result);
    }


    /**
     * 查询分数接口
     * 该方法用于查询特定数据的分数信息，通过参数从服务中请求数据，并将结果返回给调用者
     * @param params 查询条件参数，通常包括查询分数所需的必要信息如用户ID或其它标识信息
     * @return 返回一个包装的结果对象，其中包含查询到的分数信息
     */
    @IgnoreAuth
    @RequestMapping("/queryScore")
    public R queryScore(@RequestParam Map<String, Object> params) {
        // 日志记录，用于调试目的，记录当前控制器和查询参数
        logger.debug("queryScore:,,Controller:{},,params:{}", this.getClass().getName(), params);
        // 调用通用服务中的查询分数方法，传递查询参数，并接收返回的结果
        Map<String, Object> queryScore = commonService.queryScore(params);
        // 将查询结果放入R对象中，标记为成功，并返回给调用者
        return R.ok().put("data", queryScore);
    }


    /**
     * 查询字典表的分组统计总条数
     * 该方法通过接受一个参数映射表，查询字典表并返回分组统计的总条数 通过@RequestParam注解接收的参数
     * 被传递给commonService的新SelectGroupCount方法进行处理 处理结果被封装进一个R对象中，并通过
     * R.ok()方法标记为成功执行的操作，然后将查询结果放入R对象中返回
     * @param params 一个包含查询参数的映射表，用于指定查询条件
     * @return R对象封装的查询结果，包含分组统计的数据
     */
    @RequestMapping("/newSelectGroupCount")
    public R newSelectGroupCount(@RequestParam Map<String, Object> params) {
        logger.debug("newSelectGroupCount:,,Controller:{},,params:{}", this.getClass().getName(), params);
        List<Map<String, Object>> result = commonService.newSelectGroupCount(params);
        return R.ok().put("data", result);
    }


    /**
     * 根据日期格式化类型对当前表的日期进行分组求和
     * 支持按年、月、日三种方式对日期进行分组
     * 并根据分组后的日期计算总和
     * @param params 包含日期格式化类型的参数映射表
     * @return 包含分组求和结果的响应对象
     */
    @RequestMapping("/newSelectDateGroupSum")
    public R newSelectDateGroupSum(@RequestParam Map<String, Object> params) {
        // 记录进入控制器方法的调试日志，包括当前类名和参数
        logger.debug("newSelectDateGroupSum:,,Controller:{},,params:{}", this.getClass().getName(), params);
        // 根据传入的日期格式化类型获取对应的字符串表示
        String dateFormatType = String.valueOf(params.get("dateFormatType"));
        // 根据日期格式化类型设置相应的日期格式
        if ("1".equals(dateFormatType)) {
            params.put("dateFormat", "%Y");
        } else if ("2".equals(dateFormatType)) {
            params.put("dateFormat", "%Y-%m");
        } else if ("3".equals(dateFormatType)) {
            params.put("dateFormat", "%Y-%m-%d");
        } else {
            // 如果日期格式化类型不正确，返回错误响应
            return R.error("日期格式化不正确");
        }
        // 调用通用服务方法，根据参数进行分组求和
        List<Map<String, Object>> result = commonService.newSelectDateGroupSum(params);
        // 返回成功响应，包含分组求和结果
        return R.ok().put("data", result);
    }

    /**
     * 查询字典表的分组统计总条数
     * 本方法主要用于对字典表进行分组统计查询，根据日期格式化类型参数（dateFormatType）
     * 来确定日期格式，然后调用服务层方法进行统计查询，并返回查询结果。
     * @param params 查询参数，包含日期格式化类型等信息
     * @return 查询结果，包含分组统计的数据
     */
    @RequestMapping("/newSelectDateGroupCount")
    public R newSelectDateGroupCount(@RequestParam Map<String, Object> params) {
        // 记录日志，表示进入分组统计查询方法，同时记录传入的参数
        logger.debug("newSelectDateGroupCount:,,Controller:{},,params:{}", this.getClass().getName(), params);
        // 根据传入的日期格式化类型确定日期格式
        String dateFormatType = String.valueOf(params.get("dateFormatType"));
        if ("1".equals(dateFormatType)) {
            params.put("dateFormat", "%Y");
        } else if ("2".equals(dateFormatType)) {
            params.put("dateFormat", "%Y-%m");
        } else if ("3".equals(dateFormatType)) {
            params.put("dateFormat", "%Y-%m-%d");
        } else {
            // 如果日期格式化类型不正确，则返回错误信息
            return R.error("日期格式化类型不正确");
        }
        // 调用服务层方法，根据确定的日期格式进行分组统计查询
        List<Map<String, Object>> result = commonService.newSelectDateGroupCount(params);
        // 返回分组统计查询结果
        return R.ok().put("data", result);
    }
/*
 * 饼状图
 * -- 饼状图  查询当前表
 -- 				查询字典表【月】
 -- 				 统计   -- 查询某个月的每个类型的订单销售数量
 -- 				 求和   -- 查询某个月的每个类型的订单销售额
 -- 				查询某个字符串【月】
 -- 				 统计   -- 查询某个月的每个员工的订单销售数量
 -- 				 求和   -- 查询某个月的每个员工的订单销售额
 -- 				查询时间【年】
 -- 				 统计 	-- 查询每个月的订单销售数量
 -- 				 求和 	-- 查询每个月的订单销售额
 -- 饼状图  查询级联表
 -- 				查询字典表
 -- 				 统计  	-- 查询某个月的每个类型的订单销售数量
 -- 				 求和   -- 查询某个月的每个类型的订单销售额
 -- 				查询某个字符串
 -- 				 统计   -- 查询某个月的每个员工的订单销售数量
 -- 				 求和   -- 查询某个月的每个员工的订单销售额
 -- 				查询时间
 -- 				 统计 	-- 统计每个月的订单销售数量
 -- 				 求和 	-- 查询每个月的订单销售额
 */


/*
  柱状图
 -- 柱状图  查询当前表
 --             某个【年，月】
 -- 			 当前表 2 级联表 1
 -- 						统计
 --   						【日期，字符串，下拉框】
 -- 						求和
 --   						【日期，字符串，下拉框】
 -- 柱状图  查询级联表
 -- 					某个【年，月】
 -- 						统计
 --   						【日期，字符串，下拉框】
 -- 						求和
 --   						【日期，字符串，下拉框】
 */

    /**
     * 柱状图求和
     */
    @RequestMapping("/barSum")
    public R barSum(@RequestParam Map<String, Object> params) {
        logger.debug("barSum方法:,,Controller:{},,params:{}", this.getClass().getName(), com.alibaba.fastjson.JSONObject.toJSONString(params));
        Boolean isJoinTableFlag = false;//是否有级联表相关
        String one = "";//第一优先
        String two = "";//第二优先

        //处理thisTable和joinTable 处理内容是把json字符串转为Map并把带有,的切割为数组
        //当前表
        Map<String, Object> thisTable = JSON.parseObject(String.valueOf(params.get("thisTable")), Map.class);
        params.put("thisTable", thisTable);

        //级联表
        String joinTableString = String.valueOf(params.get("joinTable"));
        if (StringUtil.isNotEmpty(joinTableString)) {
            Map<String, Object> joinTable = JSON.parseObject(joinTableString, Map.class);
            params.put("joinTable", joinTable);
            isJoinTableFlag = true;
        }

        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("date")))) {//当前表日期
            thisTable.put("date", String.valueOf(thisTable.get("date")).split(","));
            one = "thisDate0";
        }
        if (isJoinTableFlag) {//级联表日期
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("date")))) {
                joinTable.put("date", String.valueOf(joinTable.get("date")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinDate0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinDate0";
                    }
                }
            }
        }
        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("string")))) {//当前表字符串
            thisTable.put("string", String.valueOf(thisTable.get("string")).split(","));
            if (StringUtil.isEmpty(one)) {
                one = "thisString0";
            } else {
                if (StringUtil.isEmpty(two)) {
                    two = "thisString0";
                }
            }
        }
        if (isJoinTableFlag) {//级联表字符串
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("string")))) {
                joinTable.put("string", String.valueOf(joinTable.get("string")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinString0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinString0";
                    }
                }
            }
        }
        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("types")))) {//当前表类型
            thisTable.put("types", String.valueOf(thisTable.get("types")).split(","));
            if (StringUtil.isEmpty(one)) {
                one = "thisTypes0";
            } else {
                if (StringUtil.isEmpty(two)) {
                    two = "thisTypes0";
                }
            }
        }
        if (isJoinTableFlag) {//级联表类型
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("types")))) {
                joinTable.put("types", String.valueOf(joinTable.get("types")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinTypes0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinTypes0";
                    }
                }

            }
        }

        List<Map<String, Object>> result = commonService.barSum(params);

        List<String> xAxis = new ArrayList<>();//报表x轴
        List<List<String>> yAxis = new ArrayList<>();//y轴
        List<String> legend = new ArrayList<>();//标题

        if (StringUtil.isEmpty(two)) {//不包含第二列
            List<String> yAxis0 = new ArrayList<>();
            yAxis.add(yAxis0);
            legend.add("数值");
            for (Map<String, Object> map : result) {
                String oneValue = String.valueOf(map.get(one));
                String value = String.valueOf(map.get("value"));
                xAxis.add(oneValue);
                yAxis0.add(value);
            }
        } else {//包含第二列
            Map<String, HashMap<String, String>> dataMap = new LinkedHashMap<>();
            if (StringUtil.isNotEmpty(two)) {
                for (Map<String, Object> map : result) {
                    String oneValue = String.valueOf(map.get(one));
                    String twoValue = String.valueOf(map.get(two));
                    String value = String.valueOf(map.get("value"));
                    if (!legend.contains(twoValue)) {
                        legend.add(twoValue);//添加完成后 就是最全的第二列的类型
                    }
                    if (dataMap.containsKey(oneValue)) {
                        dataMap.get(oneValue).put(twoValue, value);
                    } else {
                        HashMap<String, String> oneData = new HashMap<>();
                        oneData.put(twoValue, value);
                        dataMap.put(oneValue, oneData);
                    }

                }
            }

            for (int i = 0; i < legend.size(); i++) {
                yAxis.add(new ArrayList<String>());
            }

            Set<String> keys = dataMap.keySet();
            for (String key : keys) {
                xAxis.add(key);
                HashMap<String, String> map = dataMap.get(key);
                for (int i = 0; i < legend.size(); i++) {
                    List<String> data = yAxis.get(i);
                    if (StringUtil.isNotEmpty(map.get(legend.get(i)))) {
                        data.add(map.get(legend.get(i)));
                    } else {
                        data.add("0");
                    }
                }
            }
            System.out.println();
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("xAxis", xAxis);
        resultMap.put("yAxis", yAxis);
        resultMap.put("legend", legend);
        return R.ok().put("data", resultMap);
    }

    /**
     * 柱状图统计
     */
    @RequestMapping("/barCount")
    public R barCount(@RequestParam Map<String, Object> params) {
        logger.debug("barCount方法:,,Controller:{},,params:{}", this.getClass().getName(), com.alibaba.fastjson.JSONObject.toJSONString(params));
        Boolean isJoinTableFlag = false;//是否有级联表相关
        String one = "";//第一优先
        String two = "";//第二优先

        //处理thisTable和joinTable 处理内容是把json字符串转为Map并把带有,的切割为数组
        //当前表
        Map<String, Object> thisTable = JSON.parseObject(String.valueOf(params.get("thisTable")), Map.class);
        params.put("thisTable", thisTable);

        //级联表
        String joinTableString = String.valueOf(params.get("joinTable"));
        if (StringUtil.isNotEmpty(joinTableString)) {
            Map<String, Object> joinTable = JSON.parseObject(joinTableString, Map.class);
            params.put("joinTable", joinTable);
            isJoinTableFlag = true;
        }

        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("date")))) {//当前表日期
            thisTable.put("date", String.valueOf(thisTable.get("date")).split(","));
            one = "thisDate0";
        }
        if (isJoinTableFlag) {//级联表日期
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("date")))) {
                joinTable.put("date", String.valueOf(joinTable.get("date")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinDate0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinDate0";
                    }
                }
            }
        }
        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("string")))) {//当前表字符串
            thisTable.put("string", String.valueOf(thisTable.get("string")).split(","));
            if (StringUtil.isEmpty(one)) {
                one = "thisString0";
            } else {
                if (StringUtil.isEmpty(two)) {
                    two = "thisString0";
                }
            }
        }
        if (isJoinTableFlag) {//级联表字符串
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("string")))) {
                joinTable.put("string", String.valueOf(joinTable.get("string")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinString0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinString0";
                    }
                }
            }
        }
        if (StringUtil.isNotEmpty(String.valueOf(thisTable.get("types")))) {//当前表类型
            thisTable.put("types", String.valueOf(thisTable.get("types")).split(","));
            if (StringUtil.isEmpty(one)) {
                one = "thisTypes0";
            } else {
                if (StringUtil.isEmpty(two)) {
                    two = "thisTypes0";
                }
            }
        }
        if (isJoinTableFlag) {//级联表类型
            Map<String, Object> joinTable = (Map<String, Object>) params.get("joinTable");
            if (StringUtil.isNotEmpty(String.valueOf(joinTable.get("types")))) {
                joinTable.put("types", String.valueOf(joinTable.get("types")).split(","));
                if (StringUtil.isEmpty(one)) {
                    one = "joinTypes0";
                } else {
                    if (StringUtil.isEmpty(two)) {
                        two = "joinTypes0";
                    }
                }

            }
        }

        List<Map<String, Object>> result = commonService.barCount(params);

        List<String> xAxis = new ArrayList<>();//报表x轴
        List<List<String>> yAxis = new ArrayList<>();//y轴
        List<String> legend = new ArrayList<>();//标题

        if (StringUtil.isEmpty(two)) {//不包含第二列
            List<String> yAxis0 = new ArrayList<>();
            yAxis.add(yAxis0);
            legend.add("数值");
            for (Map<String, Object> map : result) {
                String oneValue = String.valueOf(map.get(one));
                String value = String.valueOf(map.get("value"));
                xAxis.add(oneValue);
                yAxis0.add(value);
            }
        } else {//包含第二列
            Map<String, HashMap<String, String>> dataMap = new LinkedHashMap<>();
            if (StringUtil.isNotEmpty(two)) {
                for (Map<String, Object> map : result) {
                    String oneValue = String.valueOf(map.get(one));
                    String twoValue = String.valueOf(map.get(two));
                    String value = String.valueOf(map.get("value"));
                    if (!legend.contains(twoValue)) {
                        legend.add(twoValue);//添加完成后 就是最全的第二列的类型
                    }
                    if (dataMap.containsKey(oneValue)) {
                        dataMap.get(oneValue).put(twoValue, value);
                    } else {
                        HashMap<String, String> oneData = new HashMap<>();
                        oneData.put(twoValue, value);
                        dataMap.put(oneValue, oneData);
                    }

                }
            }

            for (int i = 0; i < legend.size(); i++) {
                yAxis.add(new ArrayList<String>());
            }

            Set<String> keys = dataMap.keySet();
            for (String key : keys) {
                xAxis.add(key);
                HashMap<String, String> map = dataMap.get(key);
                for (int i = 0; i < legend.size(); i++) {
                    List<String> data = yAxis.get(i);
                    if (StringUtil.isNotEmpty(map.get(legend.get(i)))) {
                        data.add(map.get(legend.get(i)));
                    } else {
                        data.add("0");
                    }
                }
            }
            System.out.println();
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("xAxis", xAxis);
        resultMap.put("yAxis", yAxis);
        resultMap.put("legend", legend);
        return R.ok().put("data", resultMap);
    }
}
